• node.js

  • ¶

    Base class for all nodes in the parse tree. An instance of this class is created for each parsed node, and then extended with one of the node-type modules.

    import util from '../../util.js';
    import _ from 'lodash';
    
    export default class Node {
  • ¶

    Arguments passed in are defined by the canopy tool.

      constructor(textValue, offset, elements, properties) {
        this.textValue = textValue;
        this.offset = offset;
        this.elements = elements || [];
    
        this.properties = properties;
  • ¶

    This is the current parser state (an instance ParserState.)

        this.state = Node.state;
      }
  • ¶

    Node-type module to extend the Node instance with. Setting of this is done by canopy during parsing and is setup in parser.js.

      set module(mod) {
        _.extend(this, mod);
    
        if (this.setup) {
          this.setup();
        }
    
        _.forOwn(this.definedProperties || {}, (methods, name) => {
          Object.defineProperty(this, name, methods);
        });
    
        delete this.definedProperties;
      }
  • ¶

    The SVG element to render this node into. A node-type class is automatically added to the container. The class to set is defined on the module set during parsing.

      set container(container) {
        this._container = container;
        this._container.addClass(this.type);
      }
    
      get container() {
        return this._container;
      }
  • ¶

    The anchor defined the points on the left and right of the rendered node that the centerline of the rendered expression connects to. For most nodes, this element will be defined by the normalizeBBox method in Util.

      get anchor() {
        if (this.proxy) {
          return this.proxy.anchor;
        } else {
          return this._anchor || {};
        }
      }
  • ¶

    Returns the bounding box of the container with the anchor included.

      getBBox() {
        return _.extend(util.normalizeBBox(this.container.getBBox()), this.anchor);
      }
  • ¶

    Transforms the container.

    • matrix - A matrix transform to be applied. Created using Snap.svg.
      transform(matrix) {
        return this.container.transform(matrix);
      }
  • ¶

    Returns a Promise that will be resolved with the provided value. If the render is cancelled before the Promise is resolved, then an exception will be thrown to halt any rendering.

    • value - Value to resolve the returned promise with.
      deferredStep(value) {
        return util.tick().then(() => {
          if (this.state.cancelRender) {
            throw 'Render cancelled';
          }
    
          return value;
        });
      }
  • ¶

    Render this node.

    • container - Optional element to render this node into. A container must be specified, but if it has already been set, then it does not need to be provided to render.
      render(container) {
        if (container) {
          this.container = container;
        }
    
        if (this.proxy) {
  • ¶

    For nodes that proxy to a child node, just render the child.

          return this.proxy.render(this.container);
        } else {
  • ¶

    Non-proxied nodes call their _render method (defined by the node-type module).

          this.state.renderCounter++;
          return this._render()
            .then(() => {
              this.state.renderCounter--;
              return this;
            });
        }
      }
  • ¶

    Renders a label centered within a rectangle which can be styled. Returns a Promise which will be resolved with the SVG group the rect and text are rendered in.

    • text - String or array of strings to render as a label.
      renderLabel(text) {
        let group = this.container.group()
              .addClass('label'),
            rect = group.rect(),
            label = group.text(0, 0, _.flatten([text]));
    
        return this.deferredStep()
          .then(() => {
            let box = label.getBBox(),
                margin = 5;
    
            label.transform(Snap.matrix()
              .translate(margin, box.height / 2 + 2 * margin));
    
            rect.attr({
              width: box.width + 2 * margin,
              height: box.height + 2 * margin
            });
    
            return group;
          });
      }
  • ¶

    Renders a labeled box around another SVG element. Returns a Promise.

    • text - String or array of strings to label the box with.
    • content - SVG element to wrap in the box.
    • options.padding - Pixels of padding to place between the content and the box.
      renderLabeledBox(text, content, options) {
        let label = this.container.text(3, -3, _.flatten([text])).addClass(`${this.type}-label`);
    
        options = _.defaults(options || {}, {
          padding: 0
        });
    
        let box = this.container.rect()
              .addClass(`${this.type}-box`)
              .attr({
                rx: 3,
                ry: 3
              });
        if(options.type){
          box = this.container.rect()
              .addClass(`${options.type}-box`)
              .attr({
                rx: 3,
                ry: 3
              });
        }
    
        this.container.prepend(label);
        this.container.prepend(box);
    
        return this.deferredStep()
          .then(() => {
            let labelBox = label.getBBox(),
                contentBox = content.getBBox(),
                boxWidth = Math.max(contentBox.width + options.padding * 2, labelBox.width),
                boxHeight = contentBox.height + options.padding * 2;
  • ¶

    //matrix(1,0,0,1,-6,75) matrix = matrix.add(1,0,0,1,0,10);

            label.transform(Snap.matrix()
              .translate(0, labelBox.height));
    
            box.transform(Snap.matrix()
              .translate(0, labelBox.height))
              .attr({
                width: boxWidth,
                height: boxHeight
              });
    
            content.transform(Snap.matrix()
              .translate(boxWidth / 2 - contentBox.cx, labelBox.height + options.padding));
          });
      }
    };